package com.qingcheng.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.qingcheng.dao.SeckillGoodsMapper;
import com.qingcheng.dao.SeckillOrderMapper;
import com.qingcheng.pojo.seckill.SeckillGoods;
import com.qingcheng.pojo.seckill.SeckillOrder;
import com.qingcheng.service.seckill.SeckillOrderService;
import com.qingcheng.timer.MultiThreadingCreateOrder;
import com.qingcheng.util.IdWorker;
import com.qingcheng.util.SeckillStatus;
import org.omg.CORBA.PRIVATE_MEMBER;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;

/**
 * @Author:boy
 * @Date:2019/7/23
 * @description:
 * @ModifiedBy:
 */
@Service(interfaceClass = SeckillOrderService.class)
public class SeckillOrderServiceImpl implements SeckillOrderService {
    @Autowired
    private MultiThreadingCreateOrder multiThreadingCreateOrder;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Value("${DELAY_ORDER_EXCHANGE_BEGIN}")
    private String DELAY_ORDER_EXCHANGE_BEGIN;
    @Value("${DELAY_ORDER_QUEUE_BEGIN}")
    private String DELAY_ORDER_QUEUE_BEGIN;
    @Value("${ROUTING_KEY}")
    private String ROUTING_KEY;

    @Override
    public boolean add(Long id, String startTime, String username) {
        //判断是否有库存
        Long size = redisTemplate.boundListOps("SeckillGoodsCountList_" + id).size();
        if (size==null||size<=0){
            //没有库存
            throw  new RuntimeException("101");
        }
        //防止用户重复抢单
        Long userQueueCount = redisTemplate.boundHashOps("UserQueueCount").increment(username, 1);
        if (userQueueCount > 1) {
            //有重复排队
            throw new RuntimeException("100");
        }
        //排序信息封装
        SeckillStatus seckillStatus = new SeckillStatus(username, new Date(), 1, id, startTime);
        //将秒杀抢单信息放入redis中
        redisTemplate.boundListOps("SeckillOrderQueue").leftPush(seckillStatus);
        //保存抢单信息
        redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);
        //异步多线程操作
        multiThreadingCreateOrder.createOrder();
        return true;
    }

    @Override
    public SeckillStatus queryStatus(String username) {
        return (SeckillStatus) redisTemplate.boundHashOps("UserQueueStatus").get(username);
    }

    @Override
    public void updatePayStatus(String out_trade_no, String transaction_id, String username) {
        //从redis中获取订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
        //更新状态
        seckillOrder.setStatus("1");
        //更新支付日期
        seckillOrder.setPayTime(new Date());
        //设置交易流水号
        seckillOrder.setTransactionId(transaction_id);
        //持久化到数据库
        seckillOrderMapper.insert(seckillOrder);
        //清空缓存
        redisTemplate.boundHashOps("SeckillOrder").delete(username);
        //清空排队信息
        redisTemplate.boundHashOps("UserQueueCount").delete(username);
        //清空抢购信息
        redisTemplate.boundHashOps("UserQueueStatus").delete(username);
    }

    @Override
    public SeckillOrder findByUsername(String username) {
        //从缓存中获取用户订单
        return (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
    }

    @Override
    public void sendDelayMessage(SeckillStatus seckillStatus) {
        rabbitTemplate.convertAndSend(DELAY_ORDER_EXCHANGE_BEGIN, ROUTING_KEY, JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration(1800000+"");
                return message;
            }
        });
    }
}
